/**
 * @file launcher.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_LAUNCHER2 != 0

#include <stdio.h>

/*********************
 *      DEFINES
 *********************/
#define LAUNCHER_ANIMATION_TIME     50  //200 //LV_TABVIEW_ANIM_TIME
#define LAUNCHER_VER_ANIMATION_TIME 50  //200
#define LAUNCHER_HIDE_THRESHOLD 30

#define LAUNCHER_DROP_DOWN_START              (LV_VER_RES/4)
#define LAUNCHER_PULL_UP_START                (LV_VER_RES*3/4)

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static lv_obj_t * launcher_create(lv_obj_t * activity_obj);
static void launcher_prepare_destory(lv_obj_t * activity_obj);
static void launcher_long_press_handler(lv_obj_t * tabview);
static void launcher_tileview_event_cb(lv_obj_t * tileview, lv_event_t e);
static void sport_create(lv_obj_t * par);
static void launcher_drop_down_bar_create(lv_obj_t * activity_obj);
static void launcher_pull_up_bar_create(lv_obj_t * activity_obj);
static void launcher_drop_pull_destroy_anim_end(lv_anim_t * a);
static void launcher_drop_pull_prepare_destory(lv_obj_t * activity_obj);

/**********************
 *  STATIC VARIABLES
 **********************/
static lv_signal_cb_t  ancestor_launcher_tileview_scrl_signal;
static lv_signal_cb_t ancestor_cont_signal;
static lv_point_t * tab_valid_pos = NULL;
/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
lv_obj_t * launcher_activity_create(void)
{
    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_LAUNCHER;
    activity_ext.create = (lv_watch_activity_create_f_t)launcher_create;
    activity_ext.prepare_destory = (lv_watch_activity_prepare_destory_f_t)launcher_prepare_destory;
    lv_obj_t * obj = lv_watch_creat_activity_obj(&activity_ext);
    lv_obj_set_style_local_bg_color(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
    if(obj == NULL) return NULL;
    //printf("LAUNCHER_DESTORY_CHILDREN_WHEN_BACKGOUND =%d\n", LAUNCHER_DESTORY_CHILDREN_WHEN_BACKGOUND);

    /*Allocate the object type specific extended data*/
    lv_launcher_obj_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_launcher_obj_ext_t));
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;
    ext->pull_up_start = 0;
    for(uint8_t i = 0; i < WATCH_LAUNCHER_TAB_MAX_COUNT + 1; i++)
        ext->tab_obj[i] = NULL;
    launcher_create(obj);
    return obj;
}

void launcher_recreate(void)
{
    printf("%s\n", __FUNCTION__);
    lv_obj_t * obj = lv_watch_get_activity_obj(ACT_ID_LAUNCHER);
    launcher_prepare_destory(obj);
    lv_obj_clean(obj);
    dial_set_cont_null();
    launcher_create(obj);
}

void sport_create_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
        sport_create(NULL);
}

lv_obj_t * launcher_tileview_add_tile(lv_obj_t * tileview, uint16_t id)
{
    lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
    lv_obj_t * cont = lv_cont_create(tileview, NULL);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &lv_style_transp_tight);
    lv_obj_set_size(cont, LV_HOR_RES, LV_VER_RES);
    lv_obj_set_x(cont, LV_HOR_RES * ext->valid_pos[id].x);
    lv_tileview_add_element(tileview, cont);
    lv_obj_set_click(cont, false);
    return cont;
}

void launcher_power_key_event(void)
{
    lv_obj_t * tileview = launcher_get_tileview_obj();
    if(launcher_tileview_act_is_dial()) {
        primary_menu_create(NULL);
    } else {
        if(LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE)
            lv_tileview_set_tile_act(tileview, 1, 0, LV_ANIM_OFF);
        else
            lv_tileview_set_tile_act(tileview, 0, 0, LV_ANIM_OFF);
        dial_clock_resume_task();
    }
}

lv_obj_t * launcher_get_tab(launcher_tab_type_t type)
{
    lv_launcher_obj_ext_t * ext = lv_obj_get_ext_attr(lv_watch_get_activity_obj(ACT_ID_LAUNCHER));
    uint8_t id = launcher_tab_get_index(type);
    if(id == WATCH_LAUNCHER_TAB_MAX_COUNT) return NULL;
    if(ext->tab_obj[id] != NULL) {
        uint8_t child_cnt = lv_obj_count_children(ext->tab_obj[id]);
        if(child_cnt > 0)
            return lv_obj_get_child(ext->tab_obj[id], NULL);
    }
    if(ext->tab_obj[WATCH_LAUNCHER_TAB_MAX_COUNT] != NULL) {
        uint8_t child_cnt = lv_obj_count_children(ext->tab_obj[WATCH_LAUNCHER_TAB_MAX_COUNT]);
        if(child_cnt > 0)
            return lv_obj_get_child(ext->tab_obj[WATCH_LAUNCHER_TAB_MAX_COUNT], NULL);
    }
    return NULL;
}

bool launcher_tileview_act_is_dial(void)
{
    lv_obj_t * tileview;
    lv_tileview_ext_t * ext;
    tileview = launcher_get_tileview_obj();
    if(tileview) {
        ext = lv_obj_get_ext_attr(tileview);
        if(ext->valid_pos_cnt == 1) {
            return true;
        } else if((ext->act_id.x == 1 && LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE)
                  || (ext->act_id.x == 0 && !LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE)) {
            return true;
        }
    }
    return false;
}

lv_obj_t * launcher_get_tileview_obj(void)
{
    lv_obj_t * act_obj = lv_watch_get_activity_obj(ACT_ID_LAUNCHER);
    lv_obj_t * obj = NULL;

    _LV_LL_READ(act_obj->child_ll, obj) {
        if(lv_obj_get_event_cb(obj) == launcher_tileview_event_cb)
            break;
    }
    return obj;
}
/**********************xx
 *  STATIC FUNCTIONS
 **********************/
static lv_res_t launcher_tileview_scrl_signal(lv_obj_t * tile_scrl, lv_signal_t sign, void * param)
{
    lv_obj_t * tileview = lv_obj_get_parent(tile_scrl);
    lv_tileview_ext_t * tileview_ext = lv_obj_get_ext_attr(tileview);
    lv_point_t act_pt;
    lv_drag_dir_t drag_dir;
    static bool resume = false;
    ancestor_launcher_tileview_scrl_signal(tile_scrl, sign, param);
    if(LV_SIGNAL_PRESSED == sign) {
        dial_clock_stop_update();
    } else if(LV_SIGNAL_PRESSING == sign) {
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        drag_dir = indev->proc.types.pointer.drag_dir;
        if((drag_dir & LV_DRAG_DIR_HOR) && tileview_ext->valid_pos_cnt > 1 && LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE) {
            lv_coord_t x_coord = -lv_obj_get_width(tileview);
            lv_coord_t x_act = lv_obj_get_x(tile_scrl);
            lv_obj_t * last_tab = lv_obj_get_child(tile_scrl, NULL);
            lv_obj_t * first_tab = lv_obj_get_child_back(tile_scrl, NULL);
            uint8_t last_tab_child_cnt =  lv_obj_count_children(last_tab);
            uint8_t first_tab_child_cnt = lv_obj_count_children(first_tab);
            if(tileview_ext->act_id.x == 0) {
                if(0 == x_act && indev->proc.types.pointer.vect.x > 0) {
                    lv_tileview_set_tile_act(tileview, tileview_ext->valid_pos[tileview_ext->valid_pos_cnt - 1].x, 0, false);
                    lv_obj_t * move_cont = lv_obj_get_child(first_tab, NULL);
                    lv_obj_set_parent(move_cont, last_tab);
                }
            } else if(tileview_ext->act_id.x == 1 && -LV_VER_RES == x_act) {
                if(indev->proc.types.pointer.vect.x > 0 && last_tab_child_cnt > 0) {
                    lv_obj_t * move_cont = lv_obj_get_child(last_tab, NULL);
                    lv_obj_set_parent(move_cont, first_tab);
                    lv_watch_set_free_num(first_tab, lv_watch_get_free_num(last_tab));
                } else if(indev->proc.types.pointer.vect.x < 0 && first_tab_child_cnt > 0) {
                    lv_obj_t * move_cont = lv_obj_get_child(first_tab, NULL);
                    lv_obj_set_parent(move_cont, last_tab);
                }
            } else if(tileview_ext->act_id.x == tileview_ext->valid_pos[tileview_ext->valid_pos_cnt - 1].x) {
                if((tileview_ext->act_id.x * x_coord == x_act) && indev->proc.types.pointer.vect.x < 0) {
                    lv_tileview_set_tile_act(tileview, 0, 0, false);
                    lv_obj_t * move_cont = lv_obj_get_child(last_tab, NULL);
                    lv_obj_set_parent(move_cont, first_tab);
                }
            }
        }
        if(drag_dir & LV_DRAG_DIR_VER) {
            if(!launcher_tileview_act_is_dial()) return LV_RES_OK;
            lv_indev_get_point(indev, &act_pt);
            lv_obj_t * status_obj = lv_watch_get_activity_obj(ACT_ID_STATUS_AND_SETTING);
            if(status_obj == NULL) {
                if(act_pt.y < LAUNCHER_DROP_DOWN_START && lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_BOTTOM) {
                    launcher_drop_down_bar_create(NULL);
                    return LV_RES_OK;
                }
            } else {
                lv_obj_set_y(status_obj, act_pt.y - LV_VER_RES);
                return LV_RES_OK;
            }

            lv_obj_t * msg_obj = lv_watch_get_activity_obj(ACT_ID_MESSAGE);
            if(msg_obj == NULL) {
                if(act_pt.y > LAUNCHER_PULL_UP_START && lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_TOP)
                    launcher_pull_up_bar_create(NULL);
            } else {
                lv_obj_set_y(msg_obj, act_pt.y);
            }
        }
        return LV_RES_OK;
    } else if(LV_SIGNAL_PRESS_LOST == sign || LV_SIGNAL_RELEASED == sign) {
        lv_indev_t * indev      = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        drag_dir = indev->proc.types.pointer.drag_dir;
        lv_obj_t * status_obj = lv_watch_get_activity_obj(ACT_ID_STATUS_AND_SETTING);
        lv_obj_t * msg_obj = lv_watch_get_activity_obj(ACT_ID_MESSAGE);
        if(drag_dir & LV_DRAG_DIR_HOR) {
            if(status_obj)
                lv_obj_set_y_animation(status_obj, -LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
            else if(msg_obj)
                lv_obj_set_y_animation(msg_obj, LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
        }
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(status_obj) {
                if(act_pt.y < LV_VER_RES / 2)
                    lv_obj_set_y_animation(status_obj, -LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
                else
                    lv_obj_set_y_animation(status_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
            }

            if(msg_obj) {
                if(act_pt.y > LV_VER_RES / 2)
                    lv_obj_set_y_animation(msg_obj, LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
                else
                    lv_obj_set_y_animation(msg_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
            } else {
                dial_clock_resume_task();
            }
        }
        return LV_RES_OK;
    } else if(LV_SIGNAL_DRAG_END == sign) {
        lv_indev_t * indev      = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        if((lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_LEFT || lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_RIGHT)
                && launcher_tileview_act_is_dial()) {
            printf("drag_end\n");
            resume = true;
            if(!LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE || tileview_ext->valid_pos_cnt == 1) {
                dial_clock_resume_task();
            }
        } else {
            resume = false;
        }
    } else if(LV_SIGNAL_COORD_CHG == sign) {
        if(resume) {
            if(lv_obj_get_x(tile_scrl) == -LV_HOR_RES && LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE) {
                dial_clock_resume_task();
                resume = false;
            }
        }
    } else if(LV_SIGNAL_LONG_PRESS == sign) {
        if(launcher_tileview_act_is_dial()) {
            launcher_long_press_handler(tileview);
        }
        return LV_RES_OK;
    }

    return LV_RES_OK;
}

static void launcher_tileview_event_cb(lv_obj_t * tileview, lv_event_t e)
{
    if(LV_EVENT_VALUE_CHANGED == e) {

    }
}

static lv_obj_t * launcher_create(lv_obj_t * activity_obj)
{
    uint8_t tile_cnt = 0;
    uint8_t dial_index = 0;
    launcher_tab_read();
    uint8_t tab_cnt = launcher_tab_get_cnt();
    if(tab_cnt == 0) tile_cnt = 1; //only dial
    else {
        if(LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE) {
            tile_cnt = tab_cnt + 2;
            dial_index = 1;
        } else {
            tile_cnt = tab_cnt + 1;
        }
    }

    printf("%s:tab_cnt = %d\n", __FUNCTION__, tab_cnt);
    tab_valid_pos = (lv_point_t *)lv_mem_alloc(sizeof(lv_point_t) * (tile_cnt));
    uint8_t i = 0;
    for(i = 0; i < tile_cnt; i++) {
        tab_valid_pos[i].x = i;
        tab_valid_pos[i].y = 0;
    }

    lv_obj_t * tileview = lv_tileview_create(activity_obj, NULL);
    lv_tileview_set_valid_positions(tileview, tab_valid_pos, tile_cnt);
    lv_tileview_set_edge_flash(tileview, false);
    lv_tileview_set_anim_time(tileview, 50);
    lv_tileview_set_tab_switch_limit(tileview, 60);
    lv_obj_add_style(tileview, LV_TILEVIEW_PART_EDGE_FLASH, &lv_watch_cont_opa1);
    lv_page_set_scrollbar_mode(tileview, LV_SCROLLBAR_MODE_OFF);
    lv_obj_set_event_cb(tileview, launcher_tileview_event_cb);

    if(ancestor_launcher_tileview_scrl_signal == NULL)
        ancestor_launcher_tileview_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(tileview));
    lv_obj_set_signal_cb(lv_page_get_scrollable(tileview), launcher_tileview_scrl_signal);

    if(tile_cnt == 1) {
        dial_create(tileview, NULL, dial_index);
    } else {
        if(LAUNCHER_HOR_SLIDING_LOOP_MODE_ENABLE)
            launcher_tab_create_one(tileview);
        dial_create(tileview, NULL, dial_index);
        launcher_tab_create_all(tileview);
        lv_tileview_set_tile_act(tileview, dial_index, 0, LV_ANIM_OFF);
    }
    return tileview;
}

static void launcher_prepare_destory(lv_obj_t * activity_obj)
{
    launcher_tab_destroy();
    if(tab_valid_pos) {
        lv_mem_free(tab_valid_pos);
        tab_valid_pos = NULL;
    }
    dial_destroy();
    lv_watch_png_cache_all_free();
}

static void launcher_long_press_handler(lv_obj_t * tabview)
{
    lv_watch_png_cache_all_free();
    lv_obj_t * launcher_act_obj = lv_watch_get_activity_obj(ACT_ID_LAUNCHER);
    if(launcher_act_obj == lv_watch_get_top_activity_obj()) {
        dial_switch_create(NULL, 0);
    } else {
        printf("not create dial switch when other act(e.g. phone) create above launcher\n");
    }
}

static lv_res_t launcher_drop_down_bar_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
{
    static lv_point_t ori_pt;
    lv_point_t act_pt;
    lv_drag_dir_t drag_dir;
    lv_obj_t * act_obj = lv_watch_get_activity_obj(ACT_ID_STATUS_AND_SETTING);
    ancestor_cont_signal(obj, sign, param);
     if(LV_SIGNAL_PRESSED == sign) {
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        lv_indev_get_point(indev, &ori_pt);
    } else if(LV_SIGNAL_PRESSING == sign || LV_SIGNAL_COORD_CHG == sign) {
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        drag_dir = indev->proc.types.pointer.drag_dir;
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_TOP && act_pt.y - ori_pt.y <= -LAUNCHER_HIDE_THRESHOLD) {
                lv_obj_set_y(act_obj, act_pt.y - LV_VER_RES);
            }
        }
        return LV_RES_OK;
    } else if(LV_SIGNAL_PRESS_LOST == sign || LV_SIGNAL_RELEASED == sign || LV_SIGNAL_DRAG_END == sign) {
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        drag_dir = indev->proc.types.pointer.drag_dir;
        if(drag_dir & LV_DRAG_DIR_HOR) {
            if(lv_obj_get_y(act_obj) != 0)
                lv_obj_set_y_animation(act_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
        }
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(act_pt.y < LV_VER_RES / 2 && act_pt.y - ori_pt.y <= -LAUNCHER_HIDE_THRESHOLD) {
                lv_obj_set_y_animation(act_obj, -LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
            } else {
                lv_obj_set_y_animation(act_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
            }
        }
        return LV_RES_OK;
    }
    return LV_RES_OK;
}

static lv_res_t launcher_pull_up_bar_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
{
    lv_point_t act_pt;
    lv_drag_dir_t drag_dir;
    static lv_point_t ori_pt;
    lv_obj_t * act_obj = lv_watch_get_activity_obj(ACT_ID_MESSAGE);
    ancestor_cont_signal(obj, sign, param);
    if(LV_SIGNAL_PRESSED == sign) {
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        lv_indev_get_point(indev, &ori_pt);
    } else if(LV_SIGNAL_PRESSING == sign) {
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        drag_dir = indev->proc.types.pointer.drag_dir;
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_BOTTOM && act_pt.y - ori_pt.y >= LAUNCHER_HIDE_THRESHOLD) {
                lv_obj_set_y(act_obj, act_pt.y);
            }
        }
        return LV_RES_OK;
    } else if(LV_SIGNAL_PRESS_LOST == sign || LV_SIGNAL_RELEASED == sign) {
        printf("%s drag_end\n", __FUNCTION__);
        lv_indev_t * indev = lv_indev_get_act();
        if(indev == NULL) return LV_RES_INV;
        drag_dir = indev->proc.types.pointer.drag_dir;
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(act_pt.y > LV_VER_RES / 2 && act_pt.y - ori_pt.y >= LAUNCHER_HIDE_THRESHOLD) {
                lv_obj_set_y_animation(act_obj, LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
            } else {
                lv_obj_set_y_animation(act_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
            }
        }
        return LV_RES_OK;
    }
    return LV_RES_OK;
}

static void launcher_drop_down_bar_create(lv_obj_t * activity_obj)
{
    if(NULL == activity_obj) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_STATUS_AND_SETTING;
        activity_ext.create = (lv_watch_activity_create_f_t)launcher_drop_down_bar_create;
        activity_ext.prepare_destory = (lv_watch_activity_prepare_destory_f_t)launcher_drop_pull_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    }

    lv_obj_set_y(activity_obj, -LV_VER_RES);
    lv_obj_t * cont = lv_page_create(activity_obj, NULL);
    lv_obj_set_size(cont, LV_VER_RES, LV_HOR_RES);
    lv_obj_set_click(cont, true);
    lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
    ancestor_cont_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(cont));
    lv_obj_set_signal_cb(lv_page_get_scrollable(cont), launcher_drop_down_bar_signal);
    launcher_quick_function_create(cont);
}

static void launcher_pull_up_bar_create(lv_obj_t * activity_obj)
{
    lv_launcher_obj_ext_t * ext = lv_obj_get_ext_attr(lv_watch_get_activity_obj(ACT_ID_LAUNCHER));
    ext->pull_up_start = 1;
    lv_obj_t * msg_obj = message_create(NULL);
    lv_obj_set_y(msg_obj, LV_VER_RES);
}

void launcher_set_pull_up_signal(lv_obj_t * obj)
{
    ancestor_cont_signal = lv_obj_get_signal_cb(obj);
    lv_obj_set_signal_cb(obj, launcher_pull_up_bar_signal);
}

static void launcher_drop_pull_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();
    dial_clock_resume_task();
}

static void launcher_drop_pull_destroy_anim_end(lv_anim_t * a)
{
    lv_obj_t * activity_obj = a->var;
    launcher_drop_pull_prepare_destory(activity_obj);
    if(activity_obj) lv_obj_del(activity_obj);
}

static lv_res_t sport_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param)
{
    lv_point_t act_pt;
    lv_drag_dir_t drag_dir;
    lv_obj_t * tileview = lv_obj_get_parent(scrl);
    lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
    lv_obj_t * act_obj = lv_obj_get_parent(tileview);
    lv_indev_t * indev = lv_indev_get_act();

    ancestor_launcher_tileview_scrl_signal(scrl, sign, param);
    if(ext->act_id.x != 1) {
        if(LV_SIGNAL_DRAG_END == sign) {
            if(lv_obj_get_y(act_obj) != 0)
                lv_obj_set_y_animation(act_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
        }
        return LV_RES_OK;
    }

    if(LV_SIGNAL_PRESSING == sign) {
        drag_dir = indev->proc.types.pointer.drag_dir;
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(lv_indev_get_gesture_dir(indev) == LV_GESTURE_DIR_BOTTOM) {
                lv_obj_set_y(act_obj, act_pt.y);
            }
        }
        return LV_RES_OK;
    } else if(LV_SIGNAL_PRESS_LOST == sign || LV_SIGNAL_RELEASED == sign || LV_SIGNAL_DRAG_END == sign) {
        drag_dir = indev->proc.types.pointer.drag_dir;
        if(drag_dir & LV_DRAG_DIR_HOR) {
            if(lv_obj_get_y(act_obj) != 0)
                lv_obj_set_y_animation(act_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
        }
        if(drag_dir & LV_DRAG_DIR_VER) {
            lv_indev_get_point(indev, &act_pt);
            if(act_pt.y > LV_VER_RES / 2) {
                lv_obj_set_y_animation(act_obj, LV_VER_RES, true, LV_WATCH_OBJ_HIDE_TIME, launcher_drop_pull_destroy_anim_end);
            } else {
                lv_obj_set_y_animation(act_obj, 0, true, LV_WATCH_OBJ_HIDE_TIME, NULL);
            }
        }
        return LV_RES_OK;
    }
    return LV_RES_OK;
}
static void sport_create(lv_obj_t * activity_obj)
{
    const lv_point_t sport_pos[] = {{0, 0}, {1, 0}, {2, 0}};
    static lv_point_t sport_valid_pos[] = {
#if USE_LV_WATCH_BODYINFO != 0
        {0, 0},
#endif
#if USE_LV_WATCH_PEDOMETER != 0
        {1, 0},
#endif
#if USE_LV_WATCH_RECORD != 0
        {2, 0}
#endif
    };

    if(NULL == activity_obj) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_PEDOMETER;
        activity_ext.create = (lv_watch_activity_create_f_t)sport_create;
        activity_ext.prepare_destory = (lv_watch_activity_prepare_destory_f_t)launcher_drop_pull_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    }
    lv_obj_t * img = lv_img_create(activity_obj, NULL);
    lv_img_set_src(img, watch_get_bg());
    lv_obj_set_size(img, LV_HOR_RES, LV_VER_RES);

    lv_obj_t  * tileview = lv_tileview_create(activity_obj, NULL);
    LV_ASSERT_MEM(tileview);
    lv_tileview_set_valid_positions(tileview, sport_pos, 3);
    lv_tileview_set_edge_flash(tileview, true);
    lv_tileview_set_anim_time(tileview, 60);
    lv_page_set_scrollbar_mode(tileview, LV_SCROLLBAR_MODE_OFF);
    lv_obj_add_style(tileview, LV_TILEVIEW_PART_EDGE_FLASH, &lv_watch_cont_opa1);
    if(ancestor_launcher_tileview_scrl_signal == NULL)
        ancestor_launcher_tileview_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(tileview));
    lv_obj_set_signal_cb(lv_page_get_scrollable(tileview), sport_tileview_scrl_signal);

    lv_obj_t * tab;
#if USE_LV_WATCH_BODYINFO != 0
    tab = bodyinfo_create(tileview, 0);
    LV_ASSERT_MEM(tab);
    if(tab == NULL) return;
#endif

#if USE_LV_WATCH_PEDOMETER != 0
    tab = pedometer_create(tileview, 1);
    LV_ASSERT_MEM(tab);
    if(tab == NULL) return;
#endif

#if USE_LV_WATCH_RECORD != 0
    tab = record_create(tileview, 2);
    LV_ASSERT_MEM(tab);
    if(tab == NULL) return;
#endif
    lv_tileview_set_valid_positions(tileview, sport_valid_pos, sizeof(sport_valid_pos) / sizeof(sport_valid_pos[0]));
    lv_tileview_set_tile_act(tileview, 1, 0, false);
}
#endif/* USE_LV_WATCH_LAUNCHER*/
